package org.dbrd.preprocessor.xml;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Iterator;

import org.dbrd.model.PrecessingBugReport;
import org.dbrd.preprocessor.Preprocessor;
import org.dbrd.util.Tracer;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public abstract class XMLReportPreprocessor extends Preprocessor {

	final int firstReportId;

	final int lastReportId;

	public XMLReportPreprocessor(File target, File reportDirectory, int firstReportId, int lastReportId) {
		super(target, reportDirectory);
		this.firstReportId = firstReportId;
		this.lastReportId = lastReportId;
	}

	@Override
	protected File[] getAllReportFiles() {
		File[] reportFiles = this.reportDirectory.listFiles(new FilenameFilter() {

			@Override
			public boolean accept(File paramFile, String paramString) {
				if (paramString.endsWith(".xml")) {
					String temp=paramString.substring(0, paramString.lastIndexOf('.'));
					String[] values=temp.split("-");
					int id = Integer.parseInt(values[1]);
					
					Tracer.sinfo(" Checking ID="+id);
					return id <= lastReportId && id >= firstReportId;
				} else {
					return false;
				}
			}
		});
		return reportFiles;
	}

	protected boolean rejectBugReport(Element bugElement) {
		return false;
	}

	@SuppressWarnings("unchecked")
	@Override
	protected PrecessingBugReport[] readReport(File reportFile) {
		try {
			SAXReader reader = new SAXReader();
			reader.setValidation(false);
			reader.setEntityResolver(new EntityResolver() {

				@Override
				public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
					return new InputSource(new ByteArrayInputStream(new byte[0]));
				}
			});
			Document document = reader.read(reportFile);
			Element issuezillaElement = document.getRootElement();
			Element issueElement = (Element) issuezillaElement.elementIterator(getIssueRootTagName()).next();
			if (this.rejectBugReport(issueElement)) {
				return null;
			}
			// id
			Element idElement = (Element) issueElement.elementIterator(getIssueIdTagName()).next();
			int id = Integer.parseInt(idElement.getTextTrim());
			// summary
			Element summaryElement = (Element) issueElement.elementIterator(getSummaryTagName()).next();
			String summary = summaryElement.getText();
			// description
			Element descriptionElement = null;
			long time = 0;
			for (Iterator<Element> iter = issueElement.elementIterator(getDescriptionTagName()); iter.hasNext();) {
				Element desc = iter.next();
				long tempTime = new SimpleDateFormat(getTimeFormat()).parse(
						((Element) desc.elementIterator(getTimeTag()).next()).getText()).getTime();
				if (descriptionElement == null) {
					descriptionElement = desc;
					time = tempTime;
				} else if (tempTime < time) {
					descriptionElement = desc;
					time = tempTime;
				}
			}
			String description = ((Element) descriptionElement.elementIterator("thetext").next()).getText();

			int duplicateId = this.getDuplicateId(issueElement);

			String component = ((Element) issueElement.elementIterator(getComponentTagName()).next()).getText();
			String subComponent = ((Element) issueElement.elementIterator(getSubComponentTagName()).next()).getText();
			int priority = getPriority(issueElement);
			String version = ((Element) issueElement.elementIterator("version").next()).getText();
			String issueType = getIssueType(issueElement);

			return new PrecessingBugReport[] { new PrecessingBugReport(id, summary, description, duplicateId, priority, version,
					subComponent, issueType, component) };
		} catch (Exception e) {
			System.err.println(reportFile+ " Error Parse:"+e);
			//e.printStackTrace();
			return null;
			// throw new RuntimeException(reportFile.toString(), e);
		}
	}

	protected String getIssueType(Element issueElement) {
		return ((Element) issueElement.elementIterator(getIssueTypeTagName()).next()).getText();
	}

	protected int getPriority(Element issueElement) {
		return Integer.parseInt(((Element) issueElement.elementIterator("priority").next()).getText().substring(1));
	}

	protected abstract String getIssueTypeTagName();

	protected abstract String getSubComponentTagName();

	protected abstract String getComponentTagName();

	protected abstract int getDuplicateId(Element issueElement);

	protected String getSummaryTagName() {
		return "short_desc";
	}

	protected String getDescriptionTagName() {
		return "long_desc";
	}

	protected abstract String getTimeFormat();

	protected abstract String getTimeTag();

	protected abstract String getIssueRootTagName();

	protected abstract String getIssueIdTagName();

}
